# [九] Bean的实例化-Bean的销毁
Bean的销毁
在 bean创建完成
后就会对这个 bean注册一个销毁的 DisposableBeanAdapter
对象,Spring中就是通过DisposableBeanAdapter
类负责bean的销毁过工作。
# Bean的销毁入口
├─
getBean│ ├─
doGetBean│ │ ├─
getSingleton│ │ ├─
getObjectForBeanInstance│ │ ├─
getSingletond│ │ │ ├─
beforeSingletonCreation│ │ │ ├─
createBean│ │ │ │ ├─
doCreateBean│ │ │ │ │ ├─
createBeanInstance│ │ │ │ │ ├─
applyMergedBeanDefinitionPostProcessors│ │ │ │ │ ├─
earlySingletonExposure│ │ │ │ │ ├─
addSingletonFactory│ │ │ │ │ ├─
populateBean│ │ │ │ │ ├─
initializeBean│ │ │ │ │ └─
registerDisposableBeanIfNecessary ① bean 的销毁过程入口│ │ │ ├─
afterSingletonCreation│ │ │ └─
addSingleton
# Bean的销毁过程解析
首先我们来看一下① Bean的销毁过程:
进入 doCreateBean () 方法
类文件: org.springframework.beans.factory.support.
AbstractAutowireCapableBeanFactory
try {
...
//注册bean销毁时的类DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
进入 registerDisposableBeanIfNecessary () 方法
类文件: org.springframework.beans.factory.support.
AbstractBeanFactory
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
// 如果是单例 bean
if (mbd.isSingleton()) {
// 对这个bean注册一个销毁的Adapter对象,对给定的bean执行销毁工作
// 过滤了 DestructionAwareBeanPostProcessor 类型的接口
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 拿到bean的作用域
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
# Bean销毁的核心类
在 bean创建完成后就会对这个 bean注册一个销毁的
DisposableBeanAdapter对象
,这个类就是 销毁的核心类DisposableBeanAdapter
就是负责bean销毁
的类。在这个类中收集了该bean 是否实现了DisposableBean
接口,是否配置destroy-method
属性,如果有则 执行其destroy() 方法。
问题
① Bean的销毁过程是什么时候触发的呢?
答案
- 1、在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法,如:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml"});
// 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法
// 1、显式关闭上下文
context.close();
// 2、显式关闭上下文
context.registerShutdownHook();
- 2、在Web环境中,当
Tomcat关闭
的时候就会调用到servlet中的销毁方法
,在这个方法中就会最终也会掉用到Spring中DisposableBeanAdapter
类的destroy()
方法,该方法就会根据前面的收集进行调用。
# servlet中的销毁方法
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
public void contextInitialized(ServletContextEvent event) {
this.initWebApplicationContext(event.getServletContext());
}
// servlet中的销毁方法
public void contextDestroyed(ServletContextEvent event) {
// 该方法最终会调用Spring的DisposableBeanAdapter类的destroy()
this.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
servlet中的
closeWebApplicationContext
方法最终也会掉用到Spring中的DisposableBeanAdapter
类的destroy()
方法,该方法就会根据前面的收集进行调用。